home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / mus / edit / AlgoRhythms.lha / AlgoRhythms / Source / pitchnames.c < prev    next >
C/C++ Source or Header  |  1994-11-25  |  5KB  |  184 lines

  1. /* pitchnames.c
  2.     Copyright (c) 1993 by Thomas E. Janzen
  3.     All Rights Reserved
  4.  
  5.     THIS SOFTWARE IS FURNISHED FREE OF CHARGE FOR STUDY AND USE AND MAY
  6.     BE COPIED ONLY FOR PERSONAL USE OR COMPLETELY AS OFFERED WITH NO
  7.     CHANGES FOR FREE DISTRIBUTION.  NO TITLE TO AND OWNERSHIP OF THE
  8.     SOFTWARE IS HEREBY TRANSFERRED.  THOMAS E. JANZEN ASSUMES NO 
  9.     RESPONSIBILITY FOR THE USE OR RELIABILITY OF THIS SOFTWARE.
  10.     
  11.     Thomas E. Janzen
  12.     208A Olde Derby Road
  13.     Norwood, MA  02062-1761
  14.     (617)769-7733
  15.  
  16. **  FACILITY:
  17. **
  18. **    AlgoRhythms music improviser on Commodore (TM) Amiga (TM)
  19. **    compiled with SAS/C Amiga Compiler 6.50 
  20. **
  21. **  ABSTRACT:
  22. **
  23. **    pitchnames.c inter-converts pitch name strings and MIDI note numbers
  24. **
  25. **  AUTHORS: Thomas E. Janzen
  26. **
  27. **  CREATION DATE:    26-OCT-1993
  28. **
  29. **  MODIFICATION HISTORY:
  30. **    DATE    NAME    DESCRIPTION
  31. **-- 
  32. */
  33. #include <stdlib.h>
  34. #include <ctype.h>
  35. #include <string.h>
  36. #include <stdio.h>
  37. #include "pitchnames.h"
  38.  
  39. #define C_HAS_ACCIDENTAL (3)
  40. #define C_NO_ACCIDENTAL (2)
  41. #define C_SMALL_SCALE_LEN (7)
  42. #define C_NOTES_PER_OCTAVE (12)
  43. #define C_A (9)
  44. #define C_B (11)
  45. #define C_C (0)
  46. #define C_D (2)
  47. #define C_E (4)
  48. #define C_F (5)
  49. #define C_G (7)
  50.  
  51. int pitch_to_midi(const char *pitch_name)
  52. /*
  53. ** FUNCTIONAL DESCRIPTION:
  54. **  Converts a pitch name string to the represented MIDI note number
  55. **  ("C4" is middle C is MIDI 60; "C#4" is c-sharp above middle c (61); 
  56. **  "Cb4" and "CB4" are the C-flat (B) below middle C (59).)
  57. **  If pitch_name was invalid, a zero is returned.
  58. **
  59. ** RETURN VALUE:
  60. **      description: MIDI note number
  61. **        data_type: int
  62. **
  63. ** ARGUMENTS:
  64. **
  65. **  pitch_name-
  66. **         description: name of pitch, e.g. C4, D#2, Gb6
  67. **           data_type: pointer char
  68. **              access: read only
  69. **
  70. ** DESIGN:
  71. **  ROUTINE
  72. **  : put length of input string into pitch_name_len
  73. **  : pitch_name_letter = toupper(force pitch_name[0])
  74. **  : IF pitch_name[0] is A..G, or pitch_name length is 2 or 3
  75. **  : THEN
  76. **  : : pitch_midi = small_scale[pitch_name_letter - 'A']
  77. **  : : IF (pitch_name_len == C_HAS_ACCIDENTAL) 
  78. **  : : : SELECT toupper(pitch_name[1])
  79. **  : : : : CASE 'B'
  80. **  : : : : : lower pitch_midi by 1
  81. **  : : : : CASE '#'
  82. **  : : : : : raise pitch_midi by 1
  83. **  : : : ENDSELECT
  84. **  : : : octave = strtol(pitch_name[pitch_name_len - 1])
  85. **  : : : pitch_midi = pitch_midi + (C_NOTES_PER_OCTAVE * (octave + 1));
  86. **  : ELSE
  87. **  : : pitch_midi = 0
  88. **  : ENDIF
  89. **  : return pitch_midi
  90. **  ENDROUTINE
  91. */
  92. {
  93.     auto int    pitch_midi,
  94.                 pitch_name_len,
  95.                 octave,
  96.                 pitch_name_letter;
  97.     const static int small_scale[C_SMALL_SCALE_LEN] 
  98.         = {C_A, C_B, C_C, C_D, C_E, C_F, C_G};
  99.  
  100.     /*
  101.     ** Pre-compute the string length 
  102.     ** and force pitch_name[0] to uppercase and put into pitch_name_letter
  103.     */
  104.     pitch_name_len = strlen(pitch_name);
  105.     pitch_name_letter = toupper(pitch_name[0]);
  106.     
  107.     if (   (pitch_name_letter >= 'A') 
  108.         || (pitch_name_letter <= 'G')
  109.         || (pitch_name_len <= C_HAS_ACCIDENTAL) 
  110.         || (pitch_name_len >= C_NO_ACCIDENTAL)
  111.         )
  112.     {
  113.         /*
  114.         ** find the pre-accidental pitch number (A..G natural)
  115.         */
  116.         pitch_midi = small_scale[pitch_name_letter - 'A'];
  117.         if (C_HAS_ACCIDENTAL == pitch_name_len) 
  118.         {
  119.             /*
  120.             ** If there is an accidental (sharp # or flat b)
  121.             ** then adjust the pitch up or down a semitone
  122.             */
  123.             switch (toupper(pitch_name[1])) 
  124.             {
  125.                 case 'B':               /* a flat */
  126.                     pitch_midi -= 1;
  127.                     break;
  128.                 case '#':
  129.                     pitch_midi += 1;    /* a sharp */
  130.                     break;
  131.                 default:
  132.                     break;
  133.             }
  134.         }
  135.         /*
  136.         ** Extract the octave from the input string
  137.         */
  138.         octave = strtol(&(pitch_name[pitch_name_len - 1]), NULL, 10);
  139.         /*
  140.         ** Computer the MIDI pitch number
  141.         */
  142.         pitch_midi += (C_NOTES_PER_OCTAVE * (octave + 1));
  143.     }
  144.     else
  145.     {
  146.         /*
  147.         ** input string was bad data, so return a zero.
  148.         */
  149.         pitch_midi = 0;
  150.     }
  151.     return pitch_midi;
  152. }
  153.  
  154.  
  155.  
  156. void midi_to_pitch(const int note_num, char *pitch_name) 
  157. /*
  158. ** FUNCTIONAL DESCRIPTION:
  159. **
  160. ** ARGUMENTS:
  161. **
  162. **  note_num-
  163. **         description: MIDI note number
  164. **           data_type: int
  165. **              access: read only
  166. **
  167. **  pitch_name-
  168. **         description: string of pitch name e.g. C#4, D#2, F1, E6
  169. **           data_type: pointer to char
  170. **              access: write only
  171. **
  172. ** DESIGN:
  173. */
  174. {
  175.     /* convert MIDI note numbers to pitch name string */
  176.     /* C4 is middle C is MIDI 60 */
  177.     const char note_names[12][4] = 
  178.     {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
  179.     sprintf(pitch_name, "%s%1d", note_names[note_num % 12], 
  180.             (note_num / 12) - 1);
  181.     return;
  182. }
  183.  
  184.